/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package lolbuilder.Champions.Interf;

import java.util.ArrayList;
import lolbuilder.Champions.Impl.Caster;
import lolbuilder.Champions.Impl.GenericChamp;
import lolbuilder.build.Build;
import lolbuilder.params.Parameters;
import lolbuilder.runes.RBS;

/**
 *
 * @author maximveron
 */
public abstract class DummyChamp {
    public int LVL;
    public ArrayList<Integer> skillOrder;
    public boolean isStunned=false;
    public String name;
    public int ad;
    public int bonusad;
    public int ap;
    public int bonusap;
    public int hp;
    public int bonushp;
    public int rm;
    public int bonusrm;
    public int regenhp;
    public int bonusregenhp;
    public int arm;
    public int bonusarm;
    public int armpen;
    public int bonusarmpen;
    public int armpenPer;
    public int bonusarmpenPer;
    public int mgcpen;
    public int bonusmgcpen;
    public int mgcpenPer;
    public int bonusmgcpenPer;
    public int mana;
    public int bonusmana;
    public float cdr;
    public int bonuscdr;
    public int ls;
    public int bonusls;
    public int sv;
    public int bonussv;
    public float as;
    public float bonusas;
    public float bonusMgcDmg;
    // for madred
    public float percentHealthPerStrike;
    public int ms;
    public int bonusms;
    public int critD;
    public int bonuscritD;
    public int critP;
    public int bonuscritP;
    /*public int spellsDamage[]= {0,0,0,0};
    public float spellsADratio[] = {0,0,0,0};
    public float spellsAPratio[] = {0,0,0,0};
    public float spellsCD[] = {1,1,1,1};
    public float spellsCurrentCD[] = {0,0,0,0};
    public boolean canAdRatios[] = {false,false,false,false};
    public boolean canApRatios[] = {false,false,false,false};*/
    public ArrayList<Spell> spells=new ArrayList<Spell>();
    
    
    
    public float dpsOver100sec;
    public float burst;
    public float timeToDie;
    public boolean canResistBigBurst;
    public float dpsOver5sec;
    public float curHp;



    public void addAttackSpeed(float percentAs) {
        as=as+as*(((float)percentAs)/100);
        if (as>2.5) as=(float) 2.5;
    }
	
    public void removeAttackSpeed(float percentAs) {
        as=as-as*(((float)percentAs)/100);
        if (as<0) as=(float) 0;
    }

    public void addCritLuck(int percentCrit) {
        critP+=percentCrit;
        if (critP>100) critP=100;
    }

    public void calculateAllDatas() {
        calculateBurst();
        calculateCanResistBurst();
        calculateDpsOver100sec();
        calculateDpsOver5sec();
        calculateTimeToDie();
    }

    
    public void calculateDpsOver100sec() {
        float i=0;
        float step=(float) 0.1;
        GenericChamp g1=new GenericChamp();
        g1.arm=(Parameters.armorOfCarry+Parameters.armorOfTank)/2;
        g1.rm=(Parameters.armorOfCarry+Parameters.armorOfTank)/2;
        float totalDmg=0;
        while (i<100) {
            float MgcDamage2=this.calculateMyMagicDmgForThisNumberOfSecOnThisTarget(g1, step);

            
            float damage2=this.calculateMyDmgsForThisNumberOfSecOnThisTarget(g1,step);
            
            totalDmg+=MgcDamage2+damage2;
            i+=step;
            this.updateTick(step);
            
        }
        dpsOver100sec=totalDmg;
    }

    
    public void calculateDpsOver5sec() {
        float i=0;
        float step=(float) 0.1;
        GenericChamp g1=new GenericChamp();
        g1.arm=(Parameters.armorOfCarry+Parameters.armorOfTank)/2;
        g1.rm=(Parameters.armorOfCarry+Parameters.armorOfTank)/2;
        float totalDmg=0;
        while (i<5) {
            float MgcDamage2=this.calculateMyMagicDmgForThisNumberOfSecOnThisTarget(g1, step);

            
            float damage2=this.calculateMyDmgsForThisNumberOfSecOnThisTarget(g1,step);
            
            totalDmg+=MgcDamage2+damage2;
            i+=step;
            this.updateTick(step);
            
        }
        dpsOver5sec=totalDmg;
    }
    
    public void addCdr(float cdrPerccent) {
        this.cdr+=cdrPerccent;
        if (cdr>0.4) cdr=(float) 0.4;
    }

    public abstract void setSpells();
    
    public float calculateMyMagicDmgForThisNumberOfSecOnThisTarget(DummyChamp target, float nb_sec) {
        if (isStunned) return 0;
        int i;
        // spells f*** yeah
        float dmgFromSpells=0;
        /*for (i=0;i<4;i++) {
            spellsCurrentCD[i]+=nb_sec;
            if (spellsCurrentCD[i]>=(spellsCD[i]-(spellsCD[i]*cdr))) {
                if (canAdRatios[i]) {
                    float adDmgSpell=(spellsDamage[i]+this.ad*spellsADratio[i])-(spellsDamage[i]+this.ad*spellsADratio[i])*getPercentReducForArmorPen(target.arm);
                    dmgFromSpells+=adDmgSpell;
                } 
                if (canApRatios[i]) {
                    float apDmgSpell=(spellsDamage[i]+this.ap*spellsAPratio[i])-(spellsDamage[i]+this.ap*spellsAPratio[i])*getPercentReducForMagicPen(target.rm);
                    dmgFromSpells+=apDmgSpell;
                }
                spellsCurrentCD[i]=0;
            }
        }*/
        for (Spell s : spells) {
            dmgFromSpells+=s.getDmgDealtOnThisChamp(this, target);
        }
        float mgcDmgDealtOnAA=(float)(this.bonusMgcDmg+(target.curHp*percentHealthPerStrike));
        //deal with items like malady && wits end && madred
        float nbAttacks1ForOneSec=((float)1)*this.as;
        mgcDmgDealtOnAA*=nbAttacks1ForOneSec*nb_sec;
        mgcDmgDealtOnAA=mgcDmgDealtOnAA*getPercentReducForMagicPen(target.rm);
        float MGcDmg=dmgFromSpells+mgcDmgDealtOnAA;
        return MGcDmg;
    }
    
    public void updateTick(float nb_sec) {
        for (Spell p : spells) {
            p.updateTick(nb_sec);
        }
    }
    
    public float calculateMyDmgsForThisNumberOfSecOnThisTarget(DummyChamp target, float nb_sec) {
        if (isStunned) return 0;
        //some init
        float damageDealt;
        float critLuck1=((float)this.critP)/100;
        float nbAttacks1ForOneSec=((float)1)*this.as;
        
        
        //deal with dmg
        float Dmg1=(nbAttacks1ForOneSec-nbAttacks1ForOneSec*critLuck1)*this.ad+(((float)this.critD)/100)*nbAttacks1ForOneSec*critLuck1*this.ad;
        damageDealt=Dmg1-Dmg1*this.getPercentReducForArmorPen(target.arm);
        
        
        return (damageDealt*nb_sec);
    }
    

    
    public void calculateTimeToDie() {
        float i=(float) 0.0;
        float hploc=hp;
        float dps=Parameters.dps;
        float step=(float) 0.1;
        float lifeStealedPerStep=(this.dpsOver100sec/100)*step*((float)ls/100); //dps on 1 sec / step then * by lifesteal
        float hpPerStep=(((float)regenhp)/5)*step;
        float dpsPerStep=dps*step-((((dps*step)*getPercentReducForArmor(arm))+((dps*step)*getPercentReducForMagic(rm)))/2);
        //System.out.println(dpsPerStep);
        if (dpsPerStep<0) dpsPerStep=100;
        //System.out.println(lifeStealedPerStep);
        while (hploc>0 && i<1000) {
            hploc=hpPerStep + lifeStealedPerStep + hploc-dpsPerStep;
            //System.out.println(hploc);
            i+=step;
        }
        timeToDie=i;
        //System.out.println(timeToDie);
    }

  /*  private float sumAllBaseSpellDamage() {
        float sum=0;
        for (int i=0;i<4;i++) sum+=spellsDamage[i];
        return sum;
    }

    private float sumAllRatiosDamage() {
        float sum=0;
        for (int i=0;i<4;i++) {
            if (canAdRatios[i]) {
                sum+=spellsADratio[i]*ad+spellsAPratio[i]*ap;
            } else {
                if (spellsADratio[i]*ad>spellsAPratio[i]*ap) {
                    sum+=spellsADratio[i]*ad;
                } else {
                    sum+=spellsAPratio[i]*ap;
                }
            }
        }
        return sum;
    }
*/
   public void calculateBurst() {
        
        float totalDamage=new Caster().calculateMyDmgsForThisNumberOfSecOnThisTarget(new GenericChamp(), 1);
        float damageOntank=totalDamage-(totalDamage*getPercentReducForMagicPen(Parameters.armorOfTank));
        float damageOnCarry=totalDamage-(totalDamage*getPercentReducForMagicPen(Parameters.armorOfCarry));
        burst=(damageOnCarry+damageOntank)/2;
    }

    
    public void calculateCanResistBurst() {
        float hploc=hp;
        int dps=Parameters.dpsForBurst;
        hploc=hploc-((dps)-(((dps)*getPercentReducForArmor(arm))+((dps)*getPercentReducForMagic(rm)))/2);
        if (hploc>0) {
            canResistBigBurst=true;
        } else {
            canResistBigBurst=false;
        }
    }

    public float getPercentReducForArmorPen(float armorOfCarry) {
        float armorMinusPen=armorOfCarry-this.armpen;
        float armorMinusPercent=armorMinusPen-(armorMinusPen*(((float)armpenPer)/100));
        return (float) ((float) armorMinusPercent / (100+armorMinusPercent));
    }
    public float getPercentReducForArmor(int arm) {
        return (float) (((float) arm / (100+arm)));
    }
    public float getPercentReducForMagic(int rm) {
        return (float) (((float) rm / (100+rm)));
    }

    public float getPercentReducForMagicPen(float armorOfCarry) {
        float armorMinusPen=armorOfCarry-this.mgcpen;
        float armorMinusPercent=armorMinusPen-(armorMinusPen*(((float)mgcpenPer)/100));
        return (float) ((armorMinusPercent / (100+armorMinusPercent)));
    }

    public void printAllDatas() {
      System.out.println("dpsOver100sec "+dpsOver100sec);
      System.out.println("dpsOver5sec "+dpsOver5sec);
      System.out.println("timeToDie "+timeToDie);
      System.out.println("burst "+burst);
      System.out.println("canResistBigBurst "+canResistBigBurst);
    }


    public void resetStats() {
        this.percentHealthPerStrike=0;
        this.bonusad=0;
        this.bonusap=0;
        this.bonusarm=0;
        this.bonusarmpen=0;
        this.bonusarmpenPer=0;
        this.bonusas=0;
        this.bonuscdr=0;
        this.bonuscritD=0;
        this.bonuscritP=0;
        this.bonushp=0;
        this.bonusls=0;
        this.bonusmana=0;
        this.bonusmgcpen=0;
        this.bonusmgcpenPer=0;
        this.bonusregenhp=0;
        this.bonusMgcDmg=0;
        this.bonusms=0;
        this.bonusrm=0;
        this.bonussv=0;
        dpsOver100sec=0;
        burst=0;
        timeToDie=0;
        canResistBigBurst=false;
        dpsOver5sec=0;
    }
    
    @Override
    public String toString() {
        return name;
    }
}
